package com.timguan.render.web.common;

import com.timguan.common.cache.common.Constants;
import com.timguan.common.cache.web.CacheCommonUtil;
import net.pocrd.define.ConstField;
import net.pocrd.util.Md5Util;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * Created by guankaiqiang on 2015/1/23.
 */
public class ContextFilter implements Filter {
    private static final Logger logger = LoggerFactory.getLogger(ContextFilter.class);
    private static final String APPID_REQ_HEAD = "cms-appid";
    private static final String APPVERSION_REQ_HEAD = "cms-appversion";
    private static final String SPLITER = "|";
    private static final String UNDERLINE = "_";

    /**
     * 请求的上下文
     */
    public static class RequestContext {
        private final static ThreadLocal<RequestContext> threadLocal = new ThreadLocal<RequestContext>();
        private App app;
        private String appVersion;

        public App getApp() {
            return app;
        }

        public void setApp(App app) {
            this.app = app;
        }

        public void setAppVersion(String appVersion) {
            this.appVersion = appVersion;
        }

        public String getAppVersion() {
            return appVersion;
        }

        /**
         * 获取当前请求上下文
         */
        public static RequestContext getCurrent() {
            RequestContext current = threadLocal.get();
            if (current == null) {
                current = new RequestContext();
                threadLocal.set(current);
            }
            return current;
        }

        /**
         * 清除变量信息
         */
        public final void clear() {
            this.app = null;
            this.appVersion = null;
        }

    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    /**
     * 构造缓存Key header
     *
     * @param appId
     * @param appVersion
     * @param request
     */
    protected String buildCacheKeyHeader(int appId, String appVersion, HttpServletRequest request) {
        StringBuilder sb = new StringBuilder().append(appId).append(UNDERLINE);
        sb.append(appVersion != null ? appVersion : "").append(UNDERLINE);
        String requestURL = CacheCommonUtil.getCacheKeyByRequest(request);
        sb.append(requestURL.length() > 200 ? Md5Util.computeToHex(requestURL.getBytes(ConstField.UTF8)) : requestURL).append(SPLITER);//避免KEY过长
        //        sb.append(B2CMallServiceConfig.getInstance().getEnv()).append(SPLITER);
        return sb.toString();
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        RequestContext.getCurrent().clear();
        try {
            //解析请求的域名
            if (request instanceof HttpServletRequest && response instanceof HttpServletResponse) {
                HttpServletRequest req = (HttpServletRequest) request;
                String appId = req.getHeader(APPID_REQ_HEAD);
                String appVersion = req.getHeader(APPVERSION_REQ_HEAD);
                if (StringUtils.isNotBlank(appId) && StringUtils.isNumeric(appId)) {
                    try {
                        RequestContext.getCurrent().app = App.parseAppId(Integer.parseInt(appId));
                        RequestContext.getCurrent().appVersion = appVersion;
                    } catch (Exception e) {
                        logger.error("get appVersion failed", e);
                        RequestContext.getCurrent().app = App.parseHost(req.getHeader("host"));
                    }
                } else {
                    RequestContext.getCurrent().app = App.parseHost(req.getHeader("host"));
                }
                request.setAttribute(Constants.WEB_CACHE_KEY_HEAD,
                        buildCacheKeyHeader(RequestContext.getCurrent().app.getAppid(), RequestContext.getCurrent().appVersion, req));
            } else {
                RequestContext.getCurrent().app = App.B2CPC;
            }
            //TODO route 判断前置,转跳提前处理
            chain.doFilter(request, response);
        } finally {
            RequestContext.getCurrent().clear();
        }
    }

    @Override
    public void destroy() {

    }
}
